/*
 * This file is part of aion-engine <aion-engine.com>
 *
 * aion-engine is private software: you can redistribute it and or modify
 * it under the terms of the GNU Lesser Public License as published by
 * the Private Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * aion-engine is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser Public License for more details.
 *
 * You should have received a copy of the GNU Lesser Public License
 * along with aion-engine.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.aionengine.gameserver.model.gameobjects;

import com.aionengine.gameserver.controllers.StaticObjectController;
import com.aionengine.gameserver.model.EmotionType;
import com.aionengine.gameserver.model.templates.spawns.SpawnTemplate;
import com.aionengine.gameserver.model.templates.staticdoor.StaticDoorState;
import com.aionengine.gameserver.model.templates.staticdoor.StaticDoorTemplate;
import com.aionengine.gameserver.network.aion.serverpackets.SM_EMOTION;
import com.aionengine.gameserver.utils.PacketSendUtility;
import com.aionengine.gameserver.world.geo.GeoService;

import java.util.EnumSet;

/**
 * @author MrPoke, Rolandas
 */
public class StaticDoor extends StaticObject {

    private EnumSet<StaticDoorState> states;
    private String doorName;

    /**
     * @param objectId
     * @param controller
     * @param spawnTemplate
     * @param objectTemplate
     */
    public StaticDoor(int objectId, StaticObjectController controller, SpawnTemplate spawnTemplate, StaticDoorTemplate objectTemplate,
                      int instanceId) {
        super(objectId, controller, spawnTemplate, objectTemplate);
        states = EnumSet.copyOf(getObjectTemplate().getInitialStates());
        if (objectTemplate.getMeshFile() != null) {
            doorName = GeoService.getInstance().getDoorName(spawnTemplate.getWorldId(), objectTemplate.getMeshFile(), objectTemplate.getX(),
                    objectTemplate.getY(), objectTemplate.getZ());
        }
    }

    /**
     * @return the open state from states set
     */
    public boolean isOpen() {
        return states.contains(StaticDoorState.OPENED);
    }

    public EnumSet<StaticDoorState> getStates() {
        return states;
    }

    /**
     * @param open the open state to set
     */
    public void setOpen(boolean open) {
        EmotionType emotion;
        int packetState = 0; // not important IMO, similar to internal state
        if (open) {
            emotion = EmotionType.OPEN_DOOR;
            states.remove(StaticDoorState.CLICKABLE);
            states.add(StaticDoorState.OPENED); // 1001
            packetState = 0x9;
        } else {
            emotion = EmotionType.CLOSE_DOOR;
            if (getObjectTemplate().getInitialStates().contains(StaticDoorState.CLICKABLE))
                states.add(StaticDoorState.CLICKABLE);
            states.remove(StaticDoorState.OPENED); // 1010
            packetState = 0xA;
        }
        if (doorName != null) {
            GeoService.getInstance().setDoorState(getWorldId(), getInstanceId(), doorName, open);
        }
        // int stateFlags = StaticDoorState.getFlags(states);
        PacketSendUtility.broadcastPacket(this, new SM_EMOTION(this.getSpawn().getStaticId(), emotion, packetState));
    }

    public void changeState(boolean open, int state) {
        state = state & 0xF;
        StaticDoorState.setStates(state, states);
        EmotionType emotion = open ? emotion = EmotionType.OPEN_DOOR : EmotionType.CLOSE_DOOR;
        PacketSendUtility.broadcastPacket(this, new SM_EMOTION(this.getSpawn().getStaticId(), emotion, state));
    }

    @Override
    public StaticDoorTemplate getObjectTemplate() {
        return (StaticDoorTemplate) super.getObjectTemplate();
    }

    public String getDoorName() {
        return doorName;
    }

}
